package pl.elka.pszt.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

import pl.elka.pszt.controller.Controller;
import pl.elka.pszt.controller.event.AskEvent;
import pl.elka.pszt.controller.event.BaseEvent;
import pl.elka.pszt.controller.event.ExitEvent;
import pl.elka.pszt.controller.event.LoadKnowledgeEvent;
import pl.elka.pszt.controller.event.SetThreadsEvent;
import pl.elka.pszt.utils.Log;
import pl.elka.pszt.utils.TextUtils;
import pl.elka.pszt.utils.WindowUtils;
import pl.elka.pszt.utils.WordUtils;

/**
 * Główne okno aplikacji.
 * 
 * @author Andrzej Makarewicz
 * 
 */
public class View extends JFrame {
	
	private static final long serialVersionUID = 4516686553502994358L;
	private static final String TAG = View.class.getSimpleName();
	
	private final Controller controller;
	
	private JButton loadKnowledge, askQuestion, setThreads;
	private static final String ACTION_LOAD = "ACTION_LOAD", ACTION_ASK = "ACTION_ASK", ACTION_SET_THREADS = "ACTION_THREADS";
	
	private JTextArea textArea;
	
	public View(final Controller controller) throws HeadlessException {
		super(Constants.APP_NAME);
		
		if (controller == null) throw new NullPointerException();
		this.controller = controller;
		
		WindowUtils.setNativeLookAndFeel();
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent we) {
				BaseEvent event = new ExitEvent();
				controller.onEvent(event);
			}
		});
		setMinimumSize(new Dimension(Constants.WINDOW_MIN_WIDTH, Constants.WINDOWS_MIN_HEIGHT));
		
		WindowUtils.setWindowSizeAndLocation(this, Toolkit.getDefaultToolkit().getScreenSize(),
				Constants.WINDOW_TO_SCREEN_SIZE);
		
		initializePane();
		
		pack();
		setVisible(true);
	}
	
	/**
	 * Dodaje poszczególne elementy widoku. Przyciski na górze i panel textowy.
	 */
	private void initializePane() {
		JPanel panel = new JPanel();
		
		loadKnowledge = new JButton("Załaduj wiedzę");
		loadKnowledge.setActionCommand(ACTION_LOAD);
		loadKnowledge.addActionListener(buttonsListener);
		panel.add(loadKnowledge);
		
		askQuestion = new JButton("Zadaj pytanie");
		askQuestion.setActionCommand(ACTION_ASK);
		askQuestion.addActionListener(buttonsListener);
		panel.add(askQuestion);
		
		setThreads = new JButton("Ustaw liczbę wątków");
		setThreads.setActionCommand(ACTION_SET_THREADS);
		setThreads.addActionListener(buttonsListener);
		panel.add(setThreads);
		
		this.add(panel, BorderLayout.NORTH);
		
		textArea = new JTextArea(5,20);
		textArea.setEditable(false);
		JScrollPane scrollPane = new JScrollPane(textArea);
		this.add(scrollPane, BorderLayout.CENTER);
	}
	
	private final ActionListener buttonsListener = new ActionListener() {
		
		@Override
		public void actionPerformed(ActionEvent event) {
			switch (event.getActionCommand()) {
			case ACTION_LOAD:
				showPickKnowledgeDialog();
				break;
			case ACTION_ASK:
				showAskQuestionDialog();
				break;
			case ACTION_SET_THREADS:
				showSetThreadsDialog();
				break;
			}
		}
		
	};
	
	/**
	 * Wywoluje modalny dialog do wprowadzenia ilosci watkow.
	 */
	public void showSetThreadsDialog() {
		Runnable command = new Runnable() {
			@Override
			public void run() {
				String threads = (String) JOptionPane.showInputDialog(View.this, "Podaj liczbę wątków od 1 - 10:",
						"Wątki", JOptionPane.PLAIN_MESSAGE, null, null, null);
				
				if (isValid(threads)) {
					SetThreadsEvent event = new SetThreadsEvent(Integer.parseInt(threads));
					controller.onEvent(event);
				} else {
					showMessageDialog("Niepoprawna liczba wątków.", JOptionPane.WARNING_MESSAGE);
				}
			}
			
			private boolean isValid(String str) {
				if (TextUtils.isEmpty(str)) return false;
				
				try {
					int number = Integer.parseInt(str);
					if (number < 0 || number > 10) return false;
					
					return true;
				}
				catch (Exception e) {
					return false;
				}
			}
		};
		
		SwingUtilities.invokeLater(command);
	}
	
	/**
	 * Wywoluje modalny dialog do wprowadzenia pytania do bazy wiedzy.
	 */
	public void showAskQuestionDialog() {
		Runnable command = new Runnable() {
			@Override
			public void run() {
				String question = (String) JOptionPane.showInputDialog(View.this, "Wpisz zapytanie:", "Zapytanie",
						JOptionPane.PLAIN_MESSAGE, null, null, null);
				
				if (!TextUtils.isEmpty(question)) {
					BaseEvent event = new AskEvent(question);
					controller.onEvent(event);
				}
			}
		};
		SwingUtilities.invokeLater(command);
	}
	
	/**
	 * Pokazuje okno wyboru bazy wiedzy w pliku txt.
	 */
	public void showPickKnowledgeDialog() {
		Runnable command = new Runnable() {
			@Override
			public void run() {
				File file = FilePickingHelper.openFolderChooser(SwingUtilities.getRoot(View.this));
				if (file != null && file.exists()) {
					Log.o(TAG, "Chosen file: " + file.getAbsolutePath());
					
					BaseEvent event = new LoadKnowledgeEvent(file);
					controller.onEvent(event);
				}
			}
		};
		SwingUtilities.invokeLater(command);
	}
	/**
	 * Blokujace okienko.
	 * @param message
	 * @param messageType
	 */
	public void showMessageDialog(final String message, final int messageType) {
		String title = "";
		switch (messageType) {
		case JOptionPane.INFORMATION_MESSAGE:
			title = "Information";
			break;
		case JOptionPane.WARNING_MESSAGE:
			title = "Warning";
			break;
		case JOptionPane.ERROR_MESSAGE:
			title = "Error";
			break;
		}
		showMessageDialog(message, title, messageType);
	}
	
	/**
	 * Blokujace okienko.
	 * @param message
	 * @param title
	 * @param messageType
	 */
	public void showMessageDialog(final String message, final String title, final int messageType) {
		Runnable command = new Runnable() {
			@Override
			public void run() {
				JOptionPane.showMessageDialog(View.this, message, title, messageType);
			}
		};
		
		SwingUtilities.invokeLater(command);
	}
	
	/**
	 * Pokazuje text w polu.
	 * @param text
	 */
	public void showTextInField(final String text){
		Runnable command = new Runnable() {
			@Override
			public void run() {
				textArea.setText(WordUtils.wrap(text, 150, null, true));
			}
		};
		
		SwingUtilities.invokeLater(command);
		
	}
}
